package cn.geminis.crypto.cert.service.utils;

import cn.geminis.crypto.core.x509.X509Certificate;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.x509.X509Name;
import org.springframework.ldap.core.AttributesMapper;
import org.springframework.ldap.core.LdapTemplate;

import javax.naming.NamingException;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import java.util.Arrays;

/**
 * @author puddi
 */
public class LdapUtils {

    private static BasicAttributes create(String objectClass, String attribute, String value) {
        var attributes = new BasicAttributes();
        attributes.put(new BasicAttribute(objectClass));
        attributes.put(attribute, value);
        return attributes;
    }

    public static BasicAttributes createProvince(String name) {
        return create("locality", "st", name);
    }

    public static BasicAttributes createCity(String name) {
        return create("locality", "l", name);
    }

    public static BasicAttributes createOrg(String name) {
        return create("organization", "o", name);
    }

    public static BasicAttributes createOrgUnit(String name) {
        return create("organizationalUnit", "ou", name);
    }

    public static void createPath(LdapTemplate ldapTemplate, String dnName) {
        var dns = Arrays.stream(dnName.split(","));
        var fullDn = new StringBuilder("c=cn");

        var sts = dns.filter(dn -> dn.startsWith("ST="));
        sts.forEach(st -> {
            fullDn.append(",").append(st);
            var result = ldapTemplate.search(fullDn.toString(), "objectclass=locality", (AttributesMapper<Object>) attributes -> null);
            if (result.size() == 0) {
                var entry = createProvince(st.substring(st.indexOf("=") + 1));
                ldapTemplate.bind(fullDn.toString(), null, entry);
            }
        });

        var ls = dns.filter(dn -> dn.startsWith("L="));
        ls.forEach(l -> {
            fullDn.append(",").append(l);
            var result = ldapTemplate.search(fullDn.toString(), "objectclass=locality", (AttributesMapper<Object>) attributes -> null);
            if (result.size() == 0) {
                var entry = createCity(l.substring(l.indexOf("=") + 1));
                ldapTemplate.bind(fullDn.toString(), null, entry);
            }
        });

        var os = dns.filter(dn -> dn.startsWith("O="));
        os.forEach(o -> {
            fullDn.append(",").append(o);
            var result = ldapTemplate.search(fullDn.toString(), "objectclass=organization", (AttributesMapper<Object>) attributes -> null);
            if (result.size() == 0) {
                var entry = createCity(o.substring(o.indexOf("=") + 1));
                ldapTemplate.bind(fullDn.toString(), null, entry);
            }
        });

        var ous = dns.filter(dn -> dn.startsWith("OU="));
        ous.forEach(ou -> {
            fullDn.append(",").append(ou);
            var result = ldapTemplate.search(fullDn.toString(), "objectclass=organizationalUnit", (AttributesMapper<Object>) attributes -> null);
            if (result.size() == 0) {
                var entry = createCity(ou.substring(ou.indexOf("=") + 1));
                ldapTemplate.bind(fullDn.toString(), null, entry);
            }
        });
    }

}
